 /*******************************************************************************
  * Copyright (c) 2004, 2007 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
  * Contributors:
  * IBM Corporation - initial API and implementation
  *******************************************************************************/
 package org.eclipse.ui.ide.dialogs;

 import org.eclipse.core.resources.IContainer;
 import org.eclipse.core.resources.IFile;
 import org.eclipse.core.resources.IResource;
 import org.eclipse.core.resources.IWorkspaceRoot;
 import org.eclipse.core.runtime.Assert;
 import org.eclipse.core.runtime.CoreException;
 import org.eclipse.core.runtime.IProgressMonitor;
 import org.eclipse.core.runtime.IStatus;
 import org.eclipse.core.runtime.Status;
 import org.eclipse.core.runtime.content.IContentDescription;
 import org.eclipse.core.runtime.jobs.Job;
 import org.eclipse.jface.dialogs.DialogPage;
 import org.eclipse.jface.dialogs.IDialogConstants;
 import org.eclipse.jface.dialogs.MessageDialog;
 import org.eclipse.osgi.util.NLS;
 import org.eclipse.swt.SWT;
 import org.eclipse.swt.layout.GridData;
 import org.eclipse.swt.widgets.Composite;
 import org.eclipse.swt.widgets.Control;
 import org.eclipse.swt.widgets.Group;
 import org.eclipse.swt.widgets.Label;
 import org.eclipse.swt.widgets.Shell;
 import org.eclipse.ui.WorkbenchEncoding;
 import org.eclipse.ui.ide.IDEEncoding;
 import org.eclipse.ui.internal.ide.IDEWorkbenchMessages;
 import org.eclipse.ui.internal.ide.IDEWorkbenchPlugin;

 /**
  * The ResourceEncodingFieldEditor is a field editor for editing the encoding of
  * a resource and does not use a preference store.
  * <p>
  * This class may be instantiated; it is not intended to be subclassed.
  * </p>
  *
  * @since 3.1
  */
 public final class ResourceEncodingFieldEditor extends
         AbstractEncodingFieldEditor {

     /**
      * The resource being edited.
      */
     private IResource resource;

     private Composite group;

     /**
      * Creates a new encoding field editor for setting the encoding on the given
      * resource.
      *
      * @param labelText
      * the label text of the field editor
      * @param parent
      * the parent of the field editor's control
      * @param charsetResource
      * must be an <code>IContainer</code> or an <code>IFile</code>.
      *
      * @see org.eclipse.core.resources.IContainer#getDefaultCharset()
      * @see org.eclipse.core.resources.IFile#getCharset()
      */
     public ResourceEncodingFieldEditor(String labelText, Composite parent,
             IResource charsetResource) {
         super();
         setLabelAndResource(labelText, charsetResource);
         createControl(parent);
     }
     
     /**
      * Creates a new encoding field editor for setting the encoding on the given
      * resource.
      *
      * @param labelText
      * the label text of the field editor
      * @param parent
      * the parent of the field editor's control
      * @param charsetResource
      * must be an <code>IContainer</code> or an <code>IFile</code>.
      * @param groupTitle
      * the title for the field editor's control. If groupTitle is
      * <code>null</code> the control will be unlabelled
      * (by default a {@link Composite} instead of a {@link Group}.
      *
      * @see org.eclipse.core.resources.IContainer#getDefaultCharset()
      * @see org.eclipse.core.resources.IFile#getCharset()
      * @see AbstractEncodingFieldEditor#setGroupTitle(String)
      * @since 3.3
      */
     public ResourceEncodingFieldEditor(String labelText, Composite parent,
             IResource charsetResource,String groupTitle) {
         super();
         setLabelAndResource(labelText, charsetResource);
         setGroupTitle(groupTitle);
         createControl(parent);
     }

     /**
      * Set the label text and the resource we are editing.
      * @param labelText
      * @param charsetResource
      * @since 3.3
      */
     private void setLabelAndResource(String labelText, IResource charsetResource) {
         Assert.isTrue(charsetResource instanceof IContainer
                 || charsetResource instanceof IFile);
         setLabelText(labelText);
         this.resource = charsetResource;
     }

     /*
      * (non-Javadoc)
      *
      * @see org.eclipse.ui.internal.ide.dialogs.AbstractEncodingFieldEditor#getStoredValue()
      */
     protected String getStoredValue() {
         try {
             if (resource instanceof IContainer) {
                 return ((IContainer) resource).getDefaultCharset(false);
             }
             return ((IFile) resource).getCharset(false);

         } catch (CoreException e) {// If there is an error return the default
 IDEWorkbenchPlugin
                     .log(
                             IDEWorkbenchMessages.ResourceEncodingFieldEditor_ErrorLoadingMessage,
                             e.getStatus());
             return WorkbenchEncoding.getWorkbenchDefaultEncoding();
         }

     }

     /*
      * (non-Javadoc)
      *
      * @see org.eclipse.jface.preference.FieldEditor#doStore()
      */
     protected void doStore() {

         String encoding = getSelectedEncoding();

         // Clear the value if nothing is selected
 if (isDefaultSelected()) {
             encoding = null;
         }
         // Don't update if the same thing is selected
 if (hasSameEncoding(encoding)) {
             return;
         }

         String descriptionCharset = getCharsetFromDescription();
         if (descriptionCharset != null
                 && !(descriptionCharset.equals(encoding)) && encoding != null) {
             Shell shell = null;
             DialogPage page = getPage();
             if (page != null) {
                 shell = page.getShell();
             }

             MessageDialog dialog = new MessageDialog(
                     shell,
                     IDEWorkbenchMessages.ResourceEncodingFieldEditor_EncodingConflictTitle,
                     null,
                     NLS
                             .bind(
                                     IDEWorkbenchMessages.ResourceEncodingFieldEditor_EncodingConflictMessage,
                                     encoding, descriptionCharset),
                     MessageDialog.WARNING, new String [] {
                             IDialogConstants.YES_LABEL,
                             IDialogConstants.NO_LABEL }, 0); // yes is the
 // default
 if (dialog.open() > 0) {
                 return;
             }
         }

         IDEEncoding.addIDEEncoding(encoding);

         final String finalEncoding = encoding;

         Job charsetJob = new Job(IDEWorkbenchMessages.IDEEncoding_EncodingJob) {
             /*
              * (non-Javadoc)
              *
              * @see org.eclipse.core.runtime.jobs.Job#run(org.eclipse.core.runtime.IProgressMonitor)
              */
             protected IStatus run(IProgressMonitor monitor) {
                 try {
                     if (resource instanceof IContainer) {
                         ((IContainer) resource).setDefaultCharset(
                                 finalEncoding, monitor);
                     } else {
                         ((IFile) resource).setCharset(finalEncoding, monitor);
                     }
                     return Status.OK_STATUS;
                 } catch (CoreException e) {// If there is an error return the
 // default
 IDEWorkbenchPlugin
                             .log(
                                     IDEWorkbenchMessages.ResourceEncodingFieldEditor_ErrorStoringMessage,
                                     e.getStatus());
                     return e.getStatus();
                 }
             }
         };

         charsetJob.schedule();

     }

     /*
      * (non-Javadoc)
      *
      * @see org.eclipse.jface.preference.FieldEditor#store()
      */
     public void store() {// Override the store method as we are not using a
 // preference store
 doStore();
     }

     /*
      * (non-Javadoc)
      *
      * @see org.eclipse.jface.preference.FieldEditor#load()
      */
     public void load() {// Override the load method as we are not using a
 // preference store
 setPresentsDefaultValue(false);
         doLoad();
     }

     /*
      * (non-Javadoc)
      *
      * @see org.eclipse.jface.preference.FieldEditor#loadDefault()
      */
     public void loadDefault() {
         setPresentsDefaultValue(true);
         doLoadDefault();
         refreshValidState();
     }

     /*
      * (non-Javadoc)
      *
      * @see org.eclipse.ui.ide.dialogs.AbstractEncodingFieldEditor#findDefaultEncoding()
      */
     protected String findDefaultEncoding() {

         if (resource instanceof IWorkspaceRoot) {
             return super.findDefaultEncoding();
         }

         String defaultCharset = getCharsetFromDescription();
         defaultCharset = getCharsetFromDescription();

         if (defaultCharset != null && defaultCharset.length() > 0) {
             return defaultCharset;
         }
         try {
             // Query up the whole hierarchy
 defaultCharset = resource.getParent().getDefaultCharset(true);
         } catch (CoreException exception) {
             // If there is an exception try again
 }

         if (defaultCharset != null && defaultCharset.length() > 0) {
             return defaultCharset;
         }

         return super.findDefaultEncoding();
     }

     /**
      * Returns the charset from the content description if there is one.
      *
      * @return the charset from the content description, or <code>null</code>
      */
     private String getCharsetFromDescription() {
         IContentDescription description = getContentDescription();
         if (description != null) {
             return description.getCharset();
         }
         return null;
     }

     /*
      * (non-Javadoc)
      *
      * @see org.eclipse.ui.ide.dialogs.AbstractEncodingFieldEditor#defaultButtonText()
      */
     protected String defaultButtonText() {

         if (resource instanceof IWorkspaceRoot) {
             return super.defaultButtonText();
         }

         if (resource instanceof IFile) {
             try {
                 IContentDescription description = ((IFile) resource)
                         .getContentDescription();
                 // If we can find a charset from the description then derive
 // from that
 if (description == null || description.getCharset() == null) {
                     return NLS
                             .bind(
                                     IDEWorkbenchMessages.ResourceInfo_fileContainerEncodingFormat,
                                     getDefaultEnc());
                 }

                 return NLS
                         .bind(
                                 IDEWorkbenchMessages.ResourceInfo_fileContentEncodingFormat,
                                 getDefaultEnc());

             } catch (CoreException exception) {
                 // Do nothing here as we will just try to derive from the
 // container
 }
         }

         return NLS.bind(
                 IDEWorkbenchMessages.ResourceInfo_containerEncodingFormat,
                 getDefaultEnc());

     }

     /*
      * (non-Javadoc)
      *
      * @see org.eclipse.ui.ide.dialogs.AbstractEncodingFieldEditor#createEncodingGroup(org.eclipse.swt.widgets.Composite,
      * int)
      */
     protected Composite createEncodingGroup(Composite parent, int numColumns) {
         group = super.createEncodingGroup(parent, numColumns);
         String byteOrderLabel = IDEEncoding
                 .getByteOrderMarkLabel(getContentDescription());
         if (byteOrderLabel != null) {
             Label label = new Label(group, SWT.NONE);
             label
                     .setText(NLS
                             .bind(
                                     IDEWorkbenchMessages.WorkbenchPreference_encoding_encodingMessage,
                                     byteOrderLabel));
             GridData layoutData = new GridData();
             layoutData.horizontalSpan = numColumns + 1;
             label.setLayoutData(layoutData);

         }
         return group;
     }

     /**
      * Returns the content description of the resource if it is a file and it
      * has a content description.
      *
      * @return the content description or <code>null</code> if resource is not
      * an <code>IFile</code> or it does not have a description
      */
     private IContentDescription getContentDescription() {
         try {
             if (resource instanceof IFile) {
                 return (((IFile) resource).getContentDescription());
             }
         } catch (CoreException exception) {
             // If we cannot find it return null
 }
         return null;
     }

     /* (non-Javadoc)
      * @see org.eclipse.jface.preference.FieldEditor#setEnabled(boolean, org.eclipse.swt.widgets.Composite)
      */
     public void setEnabled(boolean enabled, Composite parent) {
         super.setEnabled(enabled, parent);
         group.setEnabled(enabled);
         Control[] children = group.getChildren();
         for (int i = 0; i < children.length; i++) {
             children[i].setEnabled(enabled);

         }
     }

 }

